﻿/******************************************************************************
 * GVideoSearch.cs
 * 
 * This module implements the GVideoSearch search class and related types.
 *  
 * Date:   12/2008
 * 
 * Copyright (c) 2009, Mark Betz 
 * 
 * All rights reserved. 
 * Redistribution and use in source and binary forms, with or without 
 * modification, are permitted provided that the following conditions are met: 
 * 
 *   * Redistributions of source code must retain the above copyright 
 *     notice, this list of conditions and the following disclaimer. 
 *   * Redistributions in binary form must reproduce the above copyright 
 *     notice, this list of conditions and the following disclaimer in the 
 *     documentation and/or other materials provided with the distribution. 
 *   * Neither the name of the Author nor the names of contributors may be 
 *     used to endorse or promote products derived from this software
 *     without specific prior written permission. 
 *     
 * THIS SOFTWARE IS PROVIDED BY MARK BETZ ''AS IS'' AND ANY  EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
 * IN NO EVENT SHALL MARK BETZ BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
 * 
 */
using System;

namespace GSearch
{
    /// <summary>
    /// Type of the event arguments to GVideoSearch events
    /// </summary>
    public class VideoSearchEventArgs : SearchEventArgs
    {
        /// <summary>
        /// Constructor used to initialize from a SearchEventArgs object.
        /// </summary>
        /// <param name="se"></param>
        public VideoSearchEventArgs(SearchEventArgs se)
            : base(se.Status, se.Result, se.Ex)
        {
        }

        /// <summary>
        /// Returns a reference to a <see cref="GSearch.GVideoResponse"/> object
        /// that contains the response, for certain event types
        /// </summary>
        public new GVideoResponse Result
        { get { return (GVideoResponse)(base.Result); } }
    }

    /// <summary>
    /// VideoSearchArgs derives from <see cref="GSearch.SearchArgs"/> and implements
    /// video search-specific arguments.
    /// <example>
    /// The following code illustrates how to create and use the VideoSearchArgs class:
    /// <code>
    /// GVideoSearch gvs = new GVideoSearch();
    /// VideoSearchArgs vsa = new VideoSearchArgs();
    /// vsa.Terms = "Top Gear Ferrari";
    /// GVideoResponse resp = gvs.Search(vsa);
    /// </code>
    /// </example>
    /// </summary>
    public class VideoSearchArgs : SearchArgs
    {
        /// <summary>
        /// Default constructor for the VideoSearchArgs class.
        /// </summary>
        public VideoSearchArgs()
        {
            VideoScoring = SearchScoring.Relevance;
        }

        /// <summary>
        /// ToQueryString overrides the base class version. It calls the
        /// base class version to get the root of the query string, and then
        /// builds the rest of the parameters.
        /// </summary>
        /// <returns>A System.String containing the complete set of querystring
        /// arguments for the specified search</returns>
        public override string ToQueryString()
        {
            string qry = base.ToQueryString();

            if ( SearchScoring.Relevance != VideoScoring )
                qry += "&scoring=d";

            return qry;
        }

        /// <summary>
        /// A value from the <see cref="GSearch.SearchScoring"/> enum giving
        /// the level of safe search filtering to be performed on results,
        /// where the highest level of filtering is Full; and the lowest
        /// is Off.
        /// </summary>
        public SearchScoring VideoScoring { get; set; }
    }

    /// <summary>
    /// The GVideoSearch class provides an interface for searching videos using Google.
    /// It derives from <see cref="GSearch.GSearchCore"/> which does a large part of
    /// the work.
    /// <example>
    /// The following example shows how to use the GVideoSearch class to search the web
    /// using Google:
    /// <code>
    /// GVideoSearch gvs = new GVideoSearch();
    /// VideoSearchArgs vsa = new VideoSearchArgs();
    /// vsa.Terms = "Top Gear Ferrari";
    /// GVideoResponse resp = gvs.Search(vsa);
    /// if ( resp.Response.Results.Length > 0 )
    ///     // process results
    /// </code>
    /// </example>
    /// </summary>
    public class GVideoSearch : GSearchCore
    {
#if (!SILVERLIGHT)
        /// <summary>
        /// Performs a syncronous search for videos using the supplied arguments. The
        /// calling thread blocks until results are returned or an exception is thrown.
        /// This method is not available in the Silverlight version of the libraries.
        /// </summary>
        /// <param name="args"><see cref="GSearch.VideoSearchArgs"/> containing the search arguments</param>
        /// <returns><see cref="GSearch.GVideoResponse"/> containing the results</returns>
        /// <exception cref="Exception">if an error occurs during the search</exception>
        public GVideoResponse Search(VideoSearchArgs args)
        {
            return (GVideoResponse)base.Search(args);
        }
#endif

        /// <summary>
        /// Peforms an asyncronous search for videos using the supplied arguments. The
        /// calling thread returns immediately, and results or errors are indicated by
        /// raising the SearchFailed, SearchComplete, or SearchProgressChanged events.
        /// Results are returned on the UI thread.
        /// </summary>
        /// <param name="args"><see cref="GSearch.VideoSearchArgs"/> containing the search arguments</param>
        /// <exception cref="Exception">if an error occurs during the search</exception>
        public void SearchAsync(VideoSearchArgs args)
        {
            base.SearchAsync(args);
        }

        /// <summary>
        /// This event is raised when the search is complete and the results are ready
        /// to be returned to the client.
        /// </summary>
        public event EventHandler<VideoSearchEventArgs> SearchComplete;

        /// <summary>
        /// This event is raised when the search fails for some reason. The event
        /// argument Ex property will reference the exception.
        /// </summary>
        public event EventHandler<VideoSearchEventArgs> SearchFailed;

        /// <summary>
        /// This event is raised when key steps in the search process are completed.
        /// See the SearchStatus enumeration for possible values for the 
        /// VideoSearchEventArgs.Status parameter.
        /// <seealso cref="GSearch.SearchStatus"/>
        /// </summary>
        public event EventHandler<VideoSearchEventArgs> SearchProgressChanged;

        /// <summary>
        /// Returns a System.String containing a complete uri for the video search
        /// service
        /// </summary>
        public override string ServiceURI
        {
            get { return base.ServiceURI + VideoResources.ServiceURI; }
        }

        /// <summary>
        /// Called by GSearchCore to raise the SearchComplete event
        /// </summary>
        /// <param name="e"><see cref="SearchEventArgs"/> containing 
        /// information about the event</param>
        protected override void OnSearchComplete(SearchEventArgs e)
        {
            EventHandler<VideoSearchEventArgs> ev = SearchComplete;
            if (null != ev)
            {
                VideoSearchEventArgs ie = new VideoSearchEventArgs(e);
                ev(this, ie);
            }
        }

        /// <summary>
        /// Called by GSearchCore to raise the SearchFailed event
        /// </summary>
        /// <param name="e"><see cref="SearchEventArgs"/> containing 
        /// information about the event</param>
        protected override void OnSearchFailed(SearchEventArgs e)
        {
            EventHandler<VideoSearchEventArgs> ev = SearchFailed;
            if (null != ev)
            {
                VideoSearchEventArgs ie = new VideoSearchEventArgs(e);
                ev(this, ie);
            }
        }

        /// <summary>
        /// Called by GSearchCore to raise the SearchProgressChanged event
        /// </summary>
        /// <param name="e"><see cref="SearchEventArgs"/> containing 
        /// information about the event</param>
        protected override void OnSearchProgressChanged(SearchEventArgs e)
        {
            EventHandler<VideoSearchEventArgs> ev = SearchProgressChanged;
            if (null != ev)
            {
                VideoSearchEventArgs ie = new VideoSearchEventArgs(e);
                ev(this, ie);
            }
        }

        /// <summary>
        /// Deserialize is called from the base when the search returns a valid
        /// result stream, it refers the call to the base class DeserializeImpl
        /// which actually does the work of deserialization.
        /// </summary>
        /// <param name="result">Stream result passed from the base class</param>
        /// <returns>Instance of <see cref="GSearch.GVideoResponse"/> as GResponse</returns>
        protected override GResponse Deserialize(System.IO.Stream result)
        {
            return DeserializeImpl<GVideoResponse>(result);
        }
    }
}
